use std::fmt;

use actix_web::{HttpResponse, Responder, ResponseError, body::BoxBody, http::StatusCode};
use rbase_macros::ImplIErrorCode;
use serde::{Deserialize, Serialize};
use serde_json::Value; // 这是处理任意 JSON 数据的类型

#[derive(Serialize, Deserialize)]
pub struct ApiResponse {
    #[serde(skip_serializing)]
    status_code: u16,

    #[serde(skip_serializing_if = "Value::is_null")]
    code: Value,

    #[serde(skip_serializing_if = "Value::is_null")]
    message: Value,

    #[serde(skip_serializing_if = "Value::is_null")]
    data: Value,

    #[serde(skip_serializing_if = "Value::is_null")]
    total: Value,
}

pub trait IErrorCode {
    fn get_code(&self) -> &str;
    fn status_code(&self) -> u16;
}

impl Default for ApiResponse {
    fn default() -> Self {
        Self {
            code: Value::Null,
            data: Value::Null,
            message: Value::Null,
            total: Value::Null,
            status_code: 200,
        }
    }
}

impl ApiResponse {
    pub fn success() -> Self {
        ApiResponse::ok(BaseError::Success)
    }
    pub fn ok(code: impl IErrorCode) -> Self {
        ApiResponse {
            status_code: code.status_code(),
            code: Value::String(code.get_code().into()),
            ..Default::default()
        }
    }
    pub fn err(code: impl IErrorCode, message: String) -> Self {
        ApiResponse {
            status_code: code.status_code(),
            code: Value::String(code.get_code().into()),
            message: Value::String(message),
            ..Default::default()
        }
    }

    pub fn data(data: impl Serialize) -> Self {
        ApiResponse {
            code: Value::String(BaseError::Success.get_code().into()),
            data: serde_json::to_value(data).unwrap_or(Value::Null),
            ..Default::default()
        }
    }

    pub fn datas(data: impl Serialize, total: i64) -> Self {
        ApiResponse {
            code: Value::String(BaseError::Success.get_code().into()),
            data: serde_json::to_value(data).unwrap_or(Value::Null),
            total: Value::Number(total.into()),
            ..Default::default()
        }
    }

    pub fn to_json(&self) -> String {
        serde_json::to_string(self).unwrap_or(serde_json::to_string(self).unwrap_or_default())
    }
}

impl Responder for ApiResponse {
    type Body = BoxBody;

    fn respond_to(self, _req: &actix_web::HttpRequest) -> actix_web::HttpResponse {
        match StatusCode::from_u16(self.status_code) {
            Ok(status_code) => HttpResponse::build(status_code).json(self),
            Err(_) => HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR).json(self),
        }
    }
}

#[derive(Debug, Clone)]
pub struct ApiError {
    status_code: u16,
    code: String,
    message: String,
}
impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Application error: {} - {}", self.code, self.message)
    }
}
impl std::error::Error for ApiError {}
impl From<anyhow::Error> for ApiError {
    fn from(err: anyhow::Error) -> Self {
        ApiError {
            status_code: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
            code: BaseError::InternalError.get_code().into(),
            message: err.to_string(),
        }
    }
}
impl ApiError {
    pub fn new(status_code: u16, code: String, message: String) -> Self {
        ApiError { status_code, code, message }
    }
}

// 关键：实现ResponseError trait
impl ResponseError for ApiError {
    // 定义错误对应的HTTP状态码
    fn status_code(&self) -> StatusCode {
        match StatusCode::from_u16(self.status_code) {
            Ok(status_code) => status_code,
            Err(_) => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }

    // 定义错误响应内容
    fn error_response(&self) -> HttpResponse {
        HttpResponse::build(self.status_code()).json(ApiResponse {
            code: Value::String(self.code.clone()),
            message: Value::String(self.message.clone()),
            ..Default::default()
        })
    }
}

impl From<serde_json::Error> for ApiError {
    fn from(_err: serde_json::Error) -> Self {
        // 将JSON解析错误映射到合适的ApiError变体
        // 这里假设ApiError有InvalidData变体可用于数据解析错误
        BaseError::InvalidRequest.into()
    }
}

#[derive(ImplIErrorCode, Debug, Clone)]
pub enum BaseError {
    #[status_code = 200]
    Success,

    #[status_code = 500]
    InternalError,

    #[status_code = 500]
    InternalErrorWithError(String),

    #[status_code = 404]
    ResourceNotFound(String),

    #[status_code = 400]
    InvalidRequest,

    #[status_code = 502]
    NetworkError(String),

    #[status_code = 403]
    PermissionDenied,

    #[status_code = 401]
    Unauthenticated,

    #[status_code = 500]
    OperationFailed(String),
}

impl From<BaseError> for ApiError {
    fn from(err: BaseError) -> Self {
        ApiError::new(err.status_code(), err.get_code().to_string(), "".to_string())
    }
}
